package com.neuron.trafikanten.views.realtime;

import java.util.ArrayList;

import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;

import com.neuron.trafikanten.R;
import com.neuron.trafikanten.dataProviders.IGenericProviderHandler;
import com.neuron.trafikanten.dataProviders.trafikanten.TrafikantenDevi;
import com.neuron.trafikanten.dataProviders.trafikanten.TrafikantenRealtime;
import com.neuron.trafikanten.dataSets.DeviData;
import com.neuron.trafikanten.dataSets.RealtimeData;
import com.neuron.trafikanten.dataSets.StationData;
import com.neuron.trafikanten.dataSets.realtime.GenericRealtimeList;
import com.neuron.trafikanten.db.FavoriteLineDbAdapter.FavoriteData;
import com.neuron.trafikanten.db.FavoriteLineDbAdapter.FavoriteStation;

public class FavoritesView extends GenericRealtimeView {
	private static final String TAG = "Trafikanten-FavoritesView";
	
	/*
	 * This is a queue of favorite stations, when size = 0 we're done loading
	 */
	private ArrayList<FavoriteStation> favStations;
	/*
	 * This is a list of actual departures generated by load().onData.
	 * Same logic as favStations when loading devi.
	 * Stations are pushed into this as favStations is cleared.
	 */
	private ArrayList<FavoriteStation> favStationsDevi;
	
	/*
	 * List of devi id's already parsed
	 */
	private ArrayList<Integer> parsedIds = new ArrayList<Integer>();
	
	/*
	 * UI
	 */
	private TextView emptyText;
	
	/** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState,"/favorites", GenericRealtimeList.RENDERER_STATION);
        
        /*
         * Setup view and adapter.
         */
        setContentView(R.layout.favorites);
        emptyText = (TextView) findViewById(R.id.emptyText);
        favStations = favoriteLineDbAdapter.getFavoriteData();
        if (favStations.size() == 0) {
        	emptyText.setVisibility(View.VISIBLE);
        }
        favStationsDevi = new ArrayList<FavoriteStation>();
        registerForContextMenu(getListView());
        /*
         * Load is triggered by onResume
         */
    }
    
    

	@Override
	protected void onResume() {
		super.onResume();
		/*
		 * Force refresh always
		 */
		onOptionsMenuRefresh();
	}



	@Override
	protected void load() {
		if (favStations.size() == 0) {
			loadDevi();
			return;
		}
    	emptyText.setVisibility(View.GONE);
		final FavoriteStation favStation = favStations.get(0);
		favStations.remove(0);
		
		//final long STARTTIME = System.currentTimeMillis();
		
		tracker.trackEvent("Data", "Favorites", "Data", 0);
		final TrafikantenRealtime realtimeProvider = createRealtimeProvider(this, favStation.station.stationId);
		realtimeProvider.start(new IGenericProviderHandler<RealtimeData>() {
			@Override
			public void onExtra(int what, Object obj) {
				switch (what) {
				case TrafikantenRealtime.MSG_TIMEDATA:
					timeDifference = (Long) obj;
					break;
				}
			}
			
			
			@Override
			public void onData(RealtimeData realtimeData) {
				final String line = realtimeData.line;
				final String destination = realtimeData.destination;
				for (FavoriteData favoriteData : favStation.items) {
					if (favoriteData.destination.equals(destination) && favoriteData.line.equals(line)) {
						realtimeList.addData(realtimeData, favStation.station);
						break;
					}
				}
			}


			@Override
			public void onPostExecute(Exception exception) {
				clearRealtimeProvider(realtimeProvider);
				//Log.d(TAG,"PERF : Download + parse of realtime data for " + favStation.station.stopName + " took " + (System.currentTimeMillis() - STARTTIME) + "ms");
				if (exception != null) {
					Log.w(TAG,"onException " + exception);
			        if (exception.getClass().getSimpleName().equals("ParseException")) {
			        	Toast.makeText(FavoritesView.this, R.string.trafikantenErrorParse, Toast.LENGTH_LONG).show();
			        } else {
			        	Toast.makeText(FavoritesView.this, R.string.trafikantenErrorOther, Toast.LENGTH_LONG).show();
			        }
				} else {
					//refreshTitle();
					/*
					 * Show info text if view is empty
					 */
					//infoText.setVisibility(realtimeList.getCount() > 0 ? View.GONE : View.VISIBLE); // note, must do this if we're done loading!
					realtimeList.notifyDataSetChanged();
					favStationsDevi.add(favStation);
					load(); // keep loading until we are done.
				}
			}

			@Override
			public void onPreExecute() {
				setProgressBarIndeterminateVisibility(true);				
			}
		});
	}
	
	
	/*
	 * NOTE, devi is not loaded in parallel with data, since some devi are duplicated.
	 * For example, we load devi id 123 that applies to both current data, and not yet loaded data. This would end up being duplicated OR ignored, which is not what we want.
	 */
	private void loadDevi() {
		if (deviProvider != null) return;
		if (favStationsDevi.size() == 0) {
			if (favStations.size() == 0) {
				setProgressBarIndeterminateVisibility(false);
			}
			return;
		}
		final FavoriteStation favStation = favStationsDevi.get(0);
		favStationsDevi.remove(0);
    	/*
    	 * Create list of lines - then merge it into a comma seperated list
    	 */
    	StringBuffer deviLines = new StringBuffer();
    	{
    		final int count = favStation.items.size();
	    	for (int i = 0; i < count; i++) {
	    		if (i > 0) {
	    			deviLines.append(",");
	    		}
	    		deviLines.append(favStation.items.get(i).line);
	    	}
    	}
    	
    	tracker.trackEvent("Data", "Favorites", "Devi", 0);
		/*
		 * Send dispatch along with devi data request.
		 */
		try {
			tracker.dispatch();
		} catch (Exception e) {}
		
    	deviProvider = new TrafikantenDevi(this, favStation.station.stationId, deviLines.toString(), new IGenericProviderHandler<DeviData>() {
    		@Override
    		public void onExtra(int what, Object obj) {
    			/* Class has no extra data */
    		}

			@Override
			public void onData(DeviData deviData) {
				if (parsedIds.contains(deviData.id)) {
					return;
				}
				if (!realtimeList.addData(deviData)) {
					// Force adding station and devi data
					realtimeList.addData(null, favStation.station);
					realtimeList.addData(deviData);
				}
				parsedIds.add(deviData.id);
			}

			@Override
			public void onPostExecute(Exception exception) {
				deviProvider = null;

				if (exception != null) {
					Log.w(TAG,"onException " + exception);
			        if (exception.getClass().getSimpleName().equals("ParseException")) {
			        	Toast.makeText(FavoritesView.this, R.string.trafikantenErrorParse, Toast.LENGTH_LONG).show();
			        } else {
			        	Toast.makeText(FavoritesView.this, R.string.trafikantenErrorOther, Toast.LENGTH_LONG).show();
			        }
				} else {
					realtimeList.notifyDataSetChanged();
				}
				loadDevi();
			}

			@Override
			public void onPreExecute() {
				setProgressBarIndeterminateVisibility(true);
			}
    	});
	}
	
    /**
     * menu code
     */
    
	@Override
	public void onOptionsMenuRefresh() {
    	stopProviders();
		clearView();
		parsedIds.clear();
    	tracker.trackEvent("Navigation", "Favorites", "Refresh", 0);
        favStations = favoriteLineDbAdapter.getFavoriteData();
        favStationsDevi = new ArrayList<FavoriteStation>();
    	load();
	}
	
	@Override
	public StationData getStation(int pos) {
		return realtimeList.getStationForRealtimeItem(pos);
	}

}
